﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Configuration;
using Slja.GSMUtility;
using Slja.GSMUtility.DAL;
using System.Threading;

namespace Slja.WinService
{
    public partial class SmsSrv : ServiceBase
    {
        private static string SmsComPort = ConfigurationManager.AppSettings["SmsComPort"];
        static int ComErrorCount = 0;        
        //private System.Threading.Mutex _mutex = new Mutex();
        private System.Timers.Timer myTimer;

        private Slja.GSMMODEM.GSMModem _gsm = Slja.GSMMODEM.GSMModem.CreateGSMModemInstance(SmsComPort, 9600);
        private Slja.GSMMODEM.GSMModem GSM
        {
            get
            {
                try
                {
                    //if (_gsm == null)
                    //{                        
                    //    // _gsm = new Slja.GSMMODEM.GSMModem(SmsComPort, 9600);                        
                    //}
                    if (!_gsm.IsOpen)
                    {
                        _gsm.Open();
                        eventLog1.WriteEntry("Com口打开成功.");
                    }
                   
                }catch(Exception err){
                    //端口错误超过60次后，停止加入日志。防止日志暴涨
                    if (ComErrorCount++ < 30)
                    {                       
                        eventLog1.WriteEntry("Com口打开失败:" + err.Message, EventLogEntryType.Error);
                        //eventLog1.WriteEntry("SljaWinService停止短信发送(" + sb.ToString() + ")");
                    }
                  
                }                
                return _gsm;
            }
        }
        public SmsSrv()
        {
            InitializeComponent();        
        }
        void GSMOnRecieved(object sender, EventArgs e)
        {
            Slja.GSMMODEM.GSMModem curGSM = (Slja.GSMMODEM.GSMModem)sender;
            int newMsgIdx = curGSM.newMsgIndex;
            string strMsg = curGSM.ReadMsgByIndex(newMsgIdx);
            string[] arr = new string[] { strMsg };
            List<SmsMsgInfo> msgList = SmsUti.ConvertRecivedMsgFormat(arr);
            //生成Model数据库列表
            List<Slja.GSMUtility.Model.sms_MsgRecive> listModel = SmsUti.AssignReciveModelList(msgList);
            //保存数据库
            Slja.GSMUtility.DAL.sms_MsgRecive dal = new Slja.GSMUtility.DAL.sms_MsgRecive();
            List<int> listid = dal.Add(listModel);
            eventLog1.WriteEntry("接收短信:" + listid[0].ToString());
        }
       
        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("SljaWinService开始启动.");
            //绑定：自动接收
            string strAutoRecvFlag = ConfigurationManager.AppSettings["SmsAutoRecive2DB"];
            if (strAutoRecvFlag.ToUpper() == "TRUE" && _gsm != null)
            {
                //绑定：自动接收,执行"阅读"动作的事件
                _gsm.OnRecieved += new Slja.GSMMODEM.GSMModem.OnRecievedHandler(GSMOnRecieved);
                //设置：自动删除
                _gsm.AutoDelMsg = true;
            }           

            //设置timer定时
            myTimer = new System.Timers.Timer(3000); 
            myTimer.Elapsed += Timer_Tick;           
            myTimer.AutoReset = true;//一直执行
            myTimer.Enabled = true;//是否引发Timer_Tick

        }

        protected override void OnStop()
        {
            try
            {
                if (_gsm.IsOpen)//此处判断用_gsm对象
                {
                    _gsm.Close();
                    eventLog1.WriteEntry("Com口关闭.");
                }
            }
            catch { eventLog1.WriteEntry("试图断开" + _gsm.ComPort + "设备出错，或设备不存在而无需断开。",EventLogEntryType.Warning); }
        }
         /// <summary>  
        /// 定时器回调处理
        /// 注意：由于串口发送短信，是独占资源，故用timer.stop和timer.start控制，事件按顺序执行;
        ///       防止发生多线程同时存在的局面。
        /// </summary>  
        /// <param name="source"></param>
        /// <param name="e"></param>
         private void Timer_Tick(object source, System.Timers.ElapsedEventArgs e)
        {
            myTimer.Stop();
            if (!GSM.IsOpen)//此处判断用GSM属性，对于端口不能开启时，具有下次打开的机会。
            {
                myTimer.Start();
                return;
            }
            ComErrorCount = 0;//置0

            //读取待发短信，发送，并记录结果            
            SendSmsMsg();
            myTimer.Start();            
            
         }
         private void SendSmsMsg()
         {
             try
             {                 
                 sms_MsgSend dal = new sms_MsgSend();
                 List<Slja.GSMUtility.Model.sms_MsgSend> List = dal.GetWaitingSendMsg();
                 //eventLog1.WriteEntry("List.Count:" + List.Count.ToString());
                 if (List.Count <= 0) { return; }

                 int n = 0;
                 uint temp;
                 //逐个号码发送一遍；若失败，会再发送，但每个号码最多重复发送3次

                 do
                 {
                     for (int i = List.Count - 1; i >= 0; i--)
                     {
                         if (List[i].SendStatus == (uint)1 //待发送状态
                             || List[i].SendStatus == (uint)3)//失败状态
                         {
                             temp = GSM.SendMsg(List[i].RecvNO, List[i].MsgContent);//(返回uint:0失败,1成功)                        
                             List[i].SendStatus = (temp == (uint)1 ? (uint)2 : (uint)3);
                         }
                     }

                 }
                 while (
                     List.Exists(delegate(Slja.GSMUtility.Model.sms_MsgSend msg) { return msg.SendStatus == 3; })
                     && n++ < 2
                     );

                 //记录结果到数据库(0待发送,1发送中，2发送成功，3发送失败)  
                 StringBuilder sb = new StringBuilder();
                 for (int j = List.Count - 1; j >= 0; j--)
                 {
                     sb.Append(List[j].ID.ToString() + ":" + List[j].SendStatus + ",");
                 }
                 dal.UpdateSendStatus(List);
                 sb.Length--;
                 eventLog1.WriteEntry("SljaWinService发送短信(" + sb.ToString() + ")");
                 //记入日志
             }
             catch (Exception err)
             {
                 eventLog1.WriteEntry("SljaWinService发送失败(" + err.Message+ ")"+err.StackTrace);
             }
         }
       
    }
}
